package com.mingqijia.gassafety.job.job.warnStrategy;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gap.cache.redis.RedisCache;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.mingqijia.gassafety.db.entity.*;
import com.mingqijia.gassafety.db.mapper.*;
import com.mingqijia.gassafety.job.dto.SendMessageDTO;
import com.mingqijia.gassafety.job.service.ConsumerService;
import com.mingqijia.gassafety.job.service.impl.CompanyServiceImpl;
import com.mingqijia.gassafety.job.service.impl.ConsumerServiceInfoServiceImpl;
import com.mingqijia.gassafety.job.service.impl.EquipmentServiceImpl;
import com.mingqijia.gassafety.job.service.impl.RunningStrategyServiceImpl;
import com.mingqijia.gassafety.job.strategy.MessageContext;
import com.mingqijia.gassafety.job.strategy.PredicateContext;
import com.mingqijia.gassafety.job.strategy.RecordService;
import com.mingqijia.gassafety.shared.constant.Constants;
import com.mingqijia.gassafety.shared.constant.MessagePushTypeEnum;
import com.mingqijia.gassafety.shared.constant.PushServicePeriodLevelEnum;
import com.mingqijia.gassafety.shared.utils.RedisCacheExt;
import com.mingqijia.gassafety.shared.utils.commonUtils.DateUtils;
import com.mingqijia.gassafety.shared.utils.message.SendMessageService;
import com.mingqijia.gassafety.shared.vcc.VccAuthoritiesProvider;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.core.log.XxlJobLogger;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author mby
 * @version 1.0.0
 * @ClassName RunningServicePeriodStrategyJob.java
 * @Description TODO
 * @createTime 2024年01月16日
 */
@Component
@Slf4j
public class RunningServicePeriodStrategyJob {

    @Autowired
    RedisCacheExt redisUtil;

    @Autowired
    DtuMapper dtuMapper;
    @Autowired
    RunningStrategyReportMapper reportMapper;

    @Autowired
    RedisCache redisCache;
    @Autowired
    ConsumerMapper consumerMapper;
    @Autowired
    RunningStrategyMapper runningStrategyMapper;
    @Autowired
    RunningStrategyExtMapper extMapper;
    @Autowired
    ContactsMapper contactsMapper;
    @Autowired
    SendMessageService sendMessageService;
    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    RunningStrategyMapper warnStrategyMapper;
    @Autowired
    WarnStrategyMapper strategyMapper;
    @Autowired
    EquipmentServiceImpl equipmentService;
    @Autowired
    CompanyServiceImpl companyService;
    @Autowired
    ConsumerServiceInfoServiceImpl consumerServiceInfoServiceImpl;

    @Autowired
    BusinessNoticeMapper noticeMapper;

    @Autowired
    JvInfoMapper jvInfoMapper;

    @Autowired
    RunningRecordMapper runningRecordMapper;

    @Autowired
    InformRecordMapper informRecordMapper;

    @Autowired
    RunningStrategyServiceImpl runningStrategyService;

    @Autowired
    ReceiverValveMapper receiverValveMapper;
    public static final String split = ";";
    public static final String split_ = "-";

    public static final Integer pageSize = 1000;
    private final Integer MaxRangeConstant = 7200000;
    //需要匹配的key
    private String patternKey_SERVICE_PERIOD = Constants.WARNING_SERVICE_PERIOD_RUNNING + ":*";

    public static final String CM_SERVICE_HOT_LINE = "cm_service_hot_line";

    public static final String OUTBOUND_CALL_CHANNEL_SETTINGS = "outbound_call_channel_settings";

    @Autowired
    VccAuthoritiesProvider provider;

    @Autowired
    DeviceStateMapper deviceStateMapper;
    @Autowired
    DtuBindingOrderMapper dtuBindingOrderMapper;
    @Autowired
    ConsumerService consumerService;

    @Autowired
    RecordReceiverValveMapper recordReceiverValveMapper;
    @Autowired
    ConsumerServiceInfoMapper consumerServiceInfoMapper;
    @Autowired
    PredicateContext predicateContext;
    @Autowired
    MessageContext messageContext;
    @Autowired
    private BusinessNoticeMapper businessNoticeMapper;

    @Autowired
    RecordService informRecordService;

    /**
     *   0 0 8-21 * * ?   每天8到21点，整点执行
     */
    @XxlJob("runningServicePeriodStrategy")
    public ReturnT<String> runningServicePeriodStrategyReport(String param) {
        XxlJobLogger.log("XXLJOB-runningServicePeriodStrategy start..." );
        log.info("runningServicePeriodStrategy--start--------");
        String key = Constants.EQUIPMENT_RUNNING_SERVICE_PERIOD_STRATEGY;
        try {
            Boolean acquire = redisUtil.setIfAbsent(key, String.valueOf(System.currentTimeMillis()), Constants.TIME_OUT);//15分钟超时
            if (acquire) {
                try {
                    execute();
                    return ReturnT.SUCCESS;
                } catch (Exception e) {
                    log.info("runningServicePeriodStrategy-error:{}", e);
                } finally {
                    redisUtil.del(key);
                }
            }
        } catch (Exception e) {
            log.info("runningServicePeriodStrategy-error:{}", e);
        }
        log.info("runningServicePeriodStrategy--end--------");
        XxlJobLogger.log("XXLJOB-runningServicePeriodStrategy end..." );
        return ReturnT.SUCCESS;
    }

    private boolean execute() {
        //当前时间
        Date now = DateUtils.nowMin();
        Date today = DateUtils.today();
        Long todayTime = today.getTime();
        log.info("runningServicePeriodStrategy-now：{},today：{}", now, today);
        //所有有效的策略
        QueryWrapper<RunningStrategy> strategyQueryWrapper = new QueryWrapper<>();
        strategyQueryWrapper.lambda().eq(RunningStrategy::getIsDeleted,0)
                .eq(RunningStrategy::getIsDisabled,0)
                .eq(RunningStrategy::getStrategyType,3)
                .orderByDesc(RunningStrategy::getStrategyObj); //根据策略对象类型降序
        List<RunningStrategy> runningStrategys = runningStrategyMapper.selectList(strategyQueryWrapper);
        //查询所有家的语音机器人（外呼）
        List<BusinessNotice> noticeList = businessNoticeMapper.selectParamCode(OUTBOUND_CALL_CHANNEL_SETTINGS);
        Map<String, BusinessNotice> noticeMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(noticeList)) {
            noticeMap = noticeList.stream().collect(Collectors.toMap(BusinessNotice::getSpId, BusinessNotice -> BusinessNotice, (k1, k2) -> k2));
        }
        log.info(" noticeMap的值为:{}", noticeMap);
        if (CollectionUtils.isNotEmpty(runningStrategys)) {
            for (RunningStrategy strategy : runningStrategys) {

                // 查询对应的策略明细
                //对应客户详细的策略信息
                QueryWrapper<RunningStrategyExt> extQueryWrapper = new QueryWrapper<>();
                extQueryWrapper.lambda().eq(RunningStrategyExt::getIsDeleted,0)
                        .in(RunningStrategyExt::getStrategyId,strategy.getId());
                List<RunningStrategyExt> runningStrategyExts = extMapper.selectList(extQueryWrapper);
                Map<String, RunningStrategyExt> strategyMap = new HashMap<>();
                if (CollectionUtils.isEmpty(runningStrategyExts)) {
                    log.info("runningServicePeriodStrategy-策略明细为空：strategyId：{}", strategy.getId());
                } else {
                    runningStrategyExts.stream().forEach(x -> {
                        strategyMap.put(new StringBuilder().append(x.getPushType()).append("-").append(x.getPushServiceExpireLevel()).toString(), x);
                    });
                    log.info("runningServicePeriodStrategy-策略明细：strategyId：{},strategyMap：{}", strategy.getId(), strategyMap);
                }

                int pageIndex = 1;
                long total = 0;
                // 公司信息
                // 公司电话
                QueryWrapper<BusinessNotice> query = new QueryWrapper<>();
                query.lambda().or().eq(BusinessNotice::getIsDeleted, 0)
                    .eq(BusinessNotice::getSpId, strategy.getSpId())
                    .eq(BusinessNotice::getParamCode, CM_SERVICE_HOT_LINE);
                List<BusinessNotice> r = noticeMapper.selectList(query);
                String phone = "";
                if (!CollectionUtil.isEmpty(r)) phone = r.get(0).getParamValue();

                String orgName = "";
                QueryWrapper<JvInfo> jvInfoQuery = new QueryWrapper<>();
                jvInfoQuery.lambda().or().eq(JvInfo::getIsDeleted, 0)
                    .eq(JvInfo::getSpId, strategy.getSpId());
                List<JvInfo> jvInfo = jvInfoMapper.selectList(jvInfoQuery);
                if (!CollectionUtil.isEmpty(jvInfo)) orgName = jvInfo.get(0).getName();
                log.info("runningServicePeriodStrategy-strategyId：{},spId：{},orgName:{},phone：{}", strategy.getId(),
                        strategy.getSpId(), orgName, phone);
                // 服务到期信息列表
                // 服务到期<=30天
                List<ConsumerServiceInfo> unexpiredList = new ArrayList<>();
                // 服务到期当天
                List<ConsumerServiceInfo> periodList = new ArrayList<>();
                // 服务超期
                List<ConsumerServiceInfo> expiredList = new ArrayList<>();
                // 查询服务到期数据
                QueryWrapper<ConsumerServiceInfo> serviceInfoQueryWrapper = new QueryWrapper<>();
                serviceInfoQueryWrapper.lambda().eq(ConsumerServiceInfo::getIsDeleted,0)
                        .eq(ConsumerServiceInfo::getIsSend,0)
                        .eq(ConsumerServiceInfo::getSpId,strategy.getSpId())
                        .le(ConsumerServiceInfo::getEndDate,DateUtils.getDiffDate(DateUtils.today(), 30));
                if (strategy.getStrategyObj() == 2) {
                    //按客户
                    String[] consumerIdArr = strategy.getStrategyObjValues().split(";");
                    serviceInfoQueryWrapper.lambda().in(ConsumerServiceInfo::getConsumerId,consumerIdArr);
                } else if (strategy.getStrategyObj() == 1) {
                    //按行业
                    String[] industryTypeArr = strategy.getStrategyObjValues().split(";");
                    serviceInfoQueryWrapper.lambda().in(ConsumerServiceInfo::getIndustryType,industryTypeArr);
                } else if (strategy.getStrategyObj() != 0) {
                    //全部客户按spId,如果策略对象不属于这三个，有问题
                    log.info("runningServicePeriodStrategy-策略对象错误：strategyId：{},strategyObj：{}", strategy.getId(), strategy.getStrategyObj());
                }
                do {
                    // 判断时间不能超过22点
                    if (new Date().getHours() > 22) {
                        log.info("runningServicePeriodStrategy-当前时间超过22点");
                        return true;
                    }
                    Page<ConsumerServiceInfo> pages = PageHelper.startPage(pageIndex, pageSize);
                    List<ConsumerServiceInfo> consumerServiceInfos = consumerServiceInfoMapper.selectList(serviceInfoQueryWrapper);
                    pageIndex++;
                    total = pages.getTotal();
                    if (CollectionUtils.isNotEmpty(consumerServiceInfos)) {
                        consumerServiceInfos.stream().forEach(service -> {
                            if (todayTime == service.getEndDate().getTime()) {
                                periodList.add(service);
                            } else if (todayTime < service.getEndDate().getTime() && service.getEndDate().getTime() - todayTime <= 30 * 24 * 60 * 60 * 1000L) {
                                unexpiredList.add(service);
                            } else if (todayTime > service.getEndDate().getTime()) {
                                expiredList.add(service);
                            }
                        });
                    }
                    // 可以发送的数据列表
                    List<SendMessageDTO> data = new ArrayList<>();
                    if (CollectionUtils.isNotEmpty(unexpiredList)) {
                        // 服务到期<=30天，执行服务到期<=30天策略，判断发送情况，组装数据
                        predicateContext.getPredicateStrategy("unexpiredPredicateStrategy").predicateStatus(strategy, data, unexpiredList, strategyMap, now, orgName, phone);
                    }
                    if (CollectionUtils.isNotEmpty(periodList)) {
                        // 服务到期当天，执行服务到期当天策略，判断发送情况，组装数据
                        predicateContext.getPredicateStrategy("periodPredicateStrategy").predicateStatus(strategy, data, periodList, strategyMap, now, orgName, phone);
                    }
                    if (CollectionUtils.isNotEmpty(expiredList)) {
                        // 服务超期，执行服务超期策略，判断发送情况，组装数据
                        predicateContext.getPredicateStrategy("expiredPredicateStrategy").predicateStatus(strategy, data, expiredList, strategyMap, now, orgName, phone);
                    }
                    log.info("runningServicePeriodStrategy-unexpiredList:{}", unexpiredList);
                    log.info("runningServicePeriodStrategy-periodList:{}", periodList);
                    log.info("runningServicePeriodStrategy-expiredList:{}", expiredList);
                    //释放资源
                    unexpiredList.clear();
                    periodList.clear();
                    expiredList.clear();
                    log.info(" data的值为:{}", data);
                    // 消息发送
                    if (CollectionUtils.isNotEmpty(data)) {
                        messageContext.getMessageStrategy("sendSmsMessageStrategy").sendMessage(data, "runningServicePeriodStrategy", informRecordService);
                        messageContext.getMessageStrategy("sendWxMessageStrategy").sendMessage(data, "runningServicePeriodStrategy", informRecordService);
                        //只有配置文件是打开状态才会发送外呼消息
                        log.info(" strategy.getSpId()的值为:{}", strategy.getSpId());
                        if (noticeMap.containsKey(strategy.getSpId())) {
                            BusinessNotice businessNotice = noticeMap.get(strategy.getSpId());
                            log.info(" businessNotice的值为:{}", businessNotice);
                            if (businessNotice != null && StringUtils.equals("ON", businessNotice.getParamValue())) {
                                messageContext.getMessageStrategy("sendCallMessageStrategy").sendMessage(data, "runningServicePeriodStrategy", informRecordService);

                            }
                        }
                    }
                    //处理缓存
                    if (CollectionUtils.isNotEmpty(data)) {
                       data.stream().forEach(x -> {
                           log.info("runningServicePeriodStrategy-setCacheMap:imei:{}}", x.getImei());
                           if (x.getCacheMap() != null) {
                               log.info("runningServicePeriodStrategy-setCacheMap:key:{},cacheMap:{}", x.getKey(), x.getCacheMap());
                               redisCache.setCacheMap(x.getKey(), x.getCacheMap());
                               // 有效时间超过最大的频率每月
                               redisTemplate.expire(x.getKey(), 32, TimeUnit.DAYS);
                               if (x.getServiceStatus() == PushServicePeriodLevelEnum.EXPIRED.getCode()
                                   && isSendEnd(strategyMap, x, MessagePushTypeEnum.SMS)
                                   && isSendEnd(strategyMap, x, MessagePushTypeEnum.WX)
                                   && isSendEnd(strategyMap, x, MessagePushTypeEnum.CALL)) {
                                   // 更新服务信息
                                   consumerServiceInfoServiceImpl.editConsumerServiceInfoIsSend(x.getImei());
                                   // 删除缓存
                                   redisCache.deleteObject(x.getKey());
                               }
                           }

                       });
                    }
                    //释放资源
                    data.clear();

                }while(total > (pageIndex - 1) * pageSize);

            }
        }

        return true;
    }


    private boolean isSendEnd(Map<String, RunningStrategyExt> strategyMap, SendMessageDTO data, MessagePushTypeEnum pushType) {
        if (strategyMap.get(new StringBuilder().append(pushType.getCode()).append("-").append(PushServicePeriodLevelEnum.EXPIRED.getCode()).toString()) == null ||
            (strategyMap.get(new StringBuilder().append(pushType.getCode()).append("-").append(PushServicePeriodLevelEnum.EXPIRED.getCode()).toString()) != null &&
            data.getCacheMap().get(pushType.getType()+"IsSend") != null &&
            Integer.parseInt(data.getCacheMap().get(pushType.getType()+"IsSend") + "") == 1)) {
            return true;
        }
        return false;
    }



}